package br.com.intelsys.basics.spring;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.springframework.ui.ModelMap;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.RedirectView;

import br.com.intelsys.basics.spring.validator.IValidatorException;
import br.com.intelsys.basics.utils.TextCleaner;

public abstract class ILocalMav extends ModelAndView {
	private static final String DESCRIPTION_DEFAULT_KEY = "global.siteDescription";
	private static Properties prop;

	private String ctrlEntity;
	private List<String> ctrlEntityList;
	private String titleKey;
	private String[] titleKeyParams;
	private String titleText;
	private String subTitleKey;
	private String[] subTitleKeyParams;
	private String subTitleText;
	private String descriptionKey;
	private String descriptionText;
	private String keywords;
	private boolean processed;
	private List<String> errorList;
	private List<String[]> paramErrorList;
	private List<String> msgList;
	private Map<String, String> commandMap;
	private Map<String, String> linkCommandMap;
	private Map<String, String> titleCommandMap;
	private boolean hideCloseCommand;
	private WebReqGeneric webReq;
	private boolean paramSupport = true;
	private List<CmdBuilderMav> cmdBuilderMavList;

	public ILocalMav(String view) {
		super(view);
	}

	public ILocalMav(View view) {
		super(view);
		paramSupport = view == null || view instanceof RedirectView == false;
	}

	public ILocalMav ctrlEntity(String ctrlEntity) {
		this.ctrlEntity = ctrlEntity;
		processed = false;
		return this;
	}

	public ILocalMav addCtrlEntity(String ctrlEntity) {
		if (ctrlEntityList == null) {
			ctrlEntityList = new ArrayList<String>();
		}
		ctrlEntityList.add(ctrlEntity);
		return this;
	}

	public ILocalMav titleText(String titleText) {
		return titleText(titleText, 0);
	}

	public ILocalMav titleText(String titleText, int wordSizeLimit) {
		if (wordSizeLimit > 0) {
			TextCleaner tc = new TextCleaner(titleText);
			tc.keepTextSizeLimit(wordSizeLimit);
			this.titleText = tc.getText();
		} else {
			this.titleText = titleText;
		}
		processed = false;
		return this;
	}

	public ILocalMav titleKey(String titleKey, String... params) {
		this.titleKey = titleKey;
		this.titleKeyParams = params;
		processed = false;
		return this;
	}

	public ILocalMav subTitleKey(String subTitleKey, String... params) {
		this.subTitleKey = subTitleKey;
		this.subTitleKeyParams = params;
		processed = false;
		return this;
	}

	public ILocalMav subTitleText(String subTitleText) {
		return subTitleText(subTitleText, 0);
	}

	public ILocalMav subTitleText(String subTitleText, int wordSizeLimit) {
		if (wordSizeLimit > 0) {
			TextCleaner tc = new TextCleaner(subTitleText);
			tc.keepTextSizeLimit(wordSizeLimit);
			this.subTitleText = tc.getText();
		} else {
			this.subTitleText = subTitleText;
		}
		processed = false;
		return this;
	}

	public ILocalMav descriptionKey(String descriptionKey) {
		this.descriptionKey = descriptionKey;
		processed = false;
		return this;
	}

	public ILocalMav descriptionKey(String descriptionKey, String... params) {
		DictionaryProperties dp = new DictionaryProperties(ctrlEntity);
		return descriptionText(dp.getProp(descriptionKey, params));
	}

	public ILocalMav descriptionText(String descriptionText) {
		this.descriptionText = descriptionText;
		processed = false;
		return this;
	}

	public ILocalMav addParam(String attributeName, Object attributeValue) {
		if (paramSupport) {
			super.addObject(attributeName, attributeValue);
		}
		return this;
	}

	public ILocalMav addParam(Object attributeValue) {
		if (paramSupport) {
			super.addObject(attributeValue);
		}
		return this;
	}

	public ILocalMav addParam(Map<String, ?> modelMap) {
		if (paramSupport) {
			super.addAllObjects(modelMap);
		}
		return this;
	}

	@Override
	@Deprecated
	public ModelAndView addObject(String attributeName, Object attributeValue) {
		if (paramSupport) {
			super.addObject(attributeName, attributeValue);
		}
		return this;
	}

	@Override
	@Deprecated
	public ModelAndView addObject(Object attributeValue) {
		if (paramSupport) {
			super.addObject(attributeValue);
		}
		return this;
	}

	@Override
	@Deprecated
	public ModelAndView addAllObjects(Map<String, ?> modelMap) {
		if (paramSupport) {
			super.addAllObjects(modelMap);
		}
		return this;
	}

	@Override
	public View getView() {
		processLocalData();
		return super.getView();
	}

	private void processLocalData() {
		if (!processed) {
			processed = true;
			prop = new DictionaryProperties(ctrlEntity);
			if (ctrlEntityList != null) {
				for (String e : ctrlEntityList) {
					((DictionaryProperties) prop).loadProperties(e);
				}
			}
			if (paramSupport) {
				super.addObject("pi", loadIPageInfo());
				super.addObject("msg", prop);
				super.addObject("tplDescription", getDescriptionContent());
				addGlobalUrlPath();
			}
		}
	}

	protected abstract IPageInfo loadIPageInfo();

	protected abstract void addGlobalUrlPath();

	protected final String getSubtitleContent() {
		String content = subTitleText != null ? subTitleText : prop.getProperty(subTitleKey != null ? subTitleKey : "");
		if (subTitleKeyParams != null && subTitleKeyParams.length > 0) {
			return DictionaryProperties.insertParamsIntoText(prop, content, subTitleKeyParams);
		} else {
			return content;
		}
	}

	protected final String getTitleContent() {
		String content = titleText != null ? titleText : prop.getProperty(titleKey != null ? titleKey : getTitle());
		if (titleKeyParams != null && titleKeyParams.length > 0) {
			return DictionaryProperties.insertParamsIntoText(prop, content, titleKeyParams);
		} else {
			return content;
		}
	}

	private String getDescriptionContent() {
		return descriptionText != null ? descriptionText : prop.getProperty(descriptionKey != null ? descriptionKey
				: DESCRIPTION_DEFAULT_KEY);
	}

	private String getTitle() {
		if (ctrlEntity == null) {
			return "";
		}
		if (ctrlEntity != null) {
			return "global.menu.label." + ctrlEntity;
		}
		return "";
	}

	@Override
	public Map<String, Object> getModel() {
		processLocalData();
		return super.getModel();
	}

	@Override
	public ModelMap getModelMap() {
		processLocalData();
		return super.getModelMap();
	}

	@Override
	public String getViewName() {
		processLocalData();
		return super.getViewName();
	}

	public ILocalMav errorList(IValidatorException e) {
		processed = false;
		if (errorList == null) {
			errorList = e.getErrorList();
			paramErrorList = e.getParamErrorList();
		} else {
			errorList.addAll(e.getErrorList());
			paramErrorList.addAll(e.getParamErrorList());
		}
		return this;
	}

	public ILocalMav addError(String string, String... param) {
		if (errorList == null) {
			errorList = new ArrayList<String>();
		}
		errorList.add(string);
		paramErrorList.add(param);
		return this;
	}

	public ILocalMav addTitleCommand(String name, String link) {
		if (titleCommandMap == null) {
			titleCommandMap = new HashMap<String, String>();
		}
		processed = false;
		titleCommandMap.put(name, link);
		return this;
	}

	public ILocalMav hideCloseCommand() {
		processed = false;
		hideCloseCommand = true;
		return this;
	}

	public ILocalMav webReq(WebReqGeneric wr) {
		processed = false;
		this.webReq = wr;
		return this;
	}

	public ILocalMav addMsg(String msgKey) {
		processed = false;
		if (msgList == null) {
			msgList = new ArrayList<String>();
		}
		msgList.add(msgKey);
		return this;
	}

	public ILocalMav addLinkCommand(String name, String jsFunction) {
		if (linkCommandMap == null) {
			linkCommandMap = new HashMap<String, String>();
		}
		processed = false;
		linkCommandMap.put(name, jsFunction);
		return this;
	}

	public ILocalMav addKey(String attributeName, String key) {
		processLocalData();
		if (paramSupport) {
			super.addObject(attributeName, key != null ? prop.getProperty(key) : null);
		}
		return this;
	}

	public ILocalMav addCmdBuilderl(CmdBuilderMav cmd) {
		processed = false;
		if (this.cmdBuilderMavList == null) {
			cmdBuilderMavList = new ArrayList<CmdBuilderMav>();
		}
		cmdBuilderMavList.add(cmd);
		return this;
	}

	protected final WebReqGeneric getWebReq() {
		return webReq;
	}

	protected final Properties getProp() {
		return prop;
	}

	protected final List<CmdBuilderMav> getCommandCtrlMavList() {
		return cmdBuilderMavList;
	}

	protected final List<String> getErrorList() {
		return errorList;
	}

	protected final List<String[]> getParamErrorList() {
		return paramErrorList;
	}

	protected final List<String> getMsgList() {
		return msgList;
	}

	protected final Map<String, String> getCommandMap() {
		return commandMap;
	}

	protected final Map<String, String> getLinkCommandMap() {
		return linkCommandMap;
	}

	protected final Map<String, String> getTitleCommandMap() {
		return titleCommandMap;
	}

	protected final boolean isHideCloseCommand() {
		return hideCloseCommand;
	}

	protected final void resetProcessed() {
		processed = false;
	}

	public ILocalMav keywords(String keywords) {
		this.keywords = keywords;
		processed = false;
		return this;
	}

	protected final String getKeywords() {
		return keywords;
	}
}
